home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PAS_0493 / VGALOAD.PAS < prev    next >
Pascal/Delphi Source File  |  1993-04-23  |  10KB  |  309 lines

  1. ─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 582 of 702                                                               
  3. From : Alex Summers                        1:103/714.0          22 Apr 93  02:05 
  4. To   : All                                                                       
  5. Subj : VGA Loaders                                                            
  6. ────────────────────────────────────────────────────────────────────────────────
  7. {      
  8.      I'm assuming that you don't understand the concept of video memory, so  
  9. I'll start off from the basics then.  Video memory is defined (for our own  
  10. purposes) as the memory that the video board scans in determining what signals 
  11. (analog) to send to the monitor.  In graphics mode, the segment of the location
  12.  
  13. of this is determined by what type of video mode you are on - 
  14. VGA/EGA modes = $A000 ($=hex), CGA modes = $B800, and Herc = $B000.  The 
  15. offsets always start off at $0. 
  16.  
  17.      Now, what type of organization are the pixels (since we're in graphics  
  18. mode) stored in?  Because of the simplicity of Mode $13 (320x200x256), most 
  19. VGA intros are written using this.  I'm not about to go ahead and explain to 
  20. you the other VGA modes dealing in the color planes, EGA/VGA registers,etc in 
  21. the higher resolution modes, there are a couple of good books out there that 
  22. can handle those of you interested in that.  Try your local bookstores and look
  23. for Power Graphics Programming by Michael Abrash, which contains his articles  
  24. about higher resolution VGA programming from Programmer's Journal.  HIGHLY  
  25. recommendable.  In any case, in this mode, each pixel on the screen  
  26. corresponds to exactly 1 byte on the video memory.  For example, location 
  27. (0,0) = Mem[$A000:0], (1,0) = Mem[$A000:1], (2,0) = Mem[A000:2], and so on. 
  28. Fairly easy eh?  Because the memory map is linear, the next line would just be 
  29. the next byte AFTER the previous line's last pixel.  For example, location 
  30. (0,319) = Mem[$A000:319], AND THEN location (1,0) = Mem[$A000:320].  And the  
  31. formula for determining the video memory location is 
  32.  
  33.      Video Mem Offset = YPos*320 + XPos 
  34.  
  35.      The actual color of the byte values stored in the video memory is 
  36. flexible and can be changed to any color of the 256,000 palette of the VGA. 
  37. This can be accomplished by altering the VGA Video DAC registers at port 
  38. addresses $3C6 through $3C9.  To read the current settings, set the Table 
  39. Read Index (port $3C7) to the color value you want, and then read the three 
  40. values from the Table Data Register (port $3C9) (one each for Red, Green, and 
  41. Blue).  Once three values have been read from that port, the current read 
  42. index is incremented by one and the next three 6 bit (range of 2, or 0 to 63) 
  43. values read are for the next color value.  Writing the to the Video DAC is 
  44. similar, except the Table Write Index is port $3C8.  Again, after writing 
  45. three successive 6 bit values to the Table Data Registers increments the Write 
  46. Index by one.  By the way, all the reference information about the Video DAC's 
  47. can be obtained from any EGA/VGA reference book.  I recommend getting 
  48. Advanced Programmer's Guide to the EGA/VGA by George Sutty and Steve Blair. 
  49.  
  50.      Waiting for the vertical retrace start signal before updating the video 
  51. memory is the key to smooth animation (with a quick memory update too of 
  52. course).  The idea is to have the screen changes "pop up" before your eyes, and
  53.  
  54. to do this, you need to make your changes just before the the screen trace 
  55. of the video memory occurs.  For this reason, updating the video memory had 
  56. better fast enough, and generally this is the part done in assembly.  The 
  57. important port and bit locations, and a sample implementation are as follows: 
  58.  
  59.        In Pascal: 
  60.  
  61.          Repeat Until (Port[$3DA] And $08) = 0; 
  62.          Repeat Until (Port[$3DA] And $08) <> 0; 
  63.  
  64.        And in Assembly: 
  65.  
  66.                    MOV   DX,3DAh 
  67.          Wait:     IN    AL,DX 
  68.                    TEST  AL,08h 
  69.                    JZ    Wait 
  70.          Retr:     IN    AL,DX 
  71.                    TEST  AL,08h 
  72.                    JNZ   Retr 
  73.  
  74.  
  75.      And finally, how to get the characters on the screen.  I used the old 
  76. character set that's stored in BIOS because it saves time and space (instead 
  77. of capturing a graphical message).  The memory address for this is 
  78. $F000:$FA6E.  Because the character set is 8 bits by 8 bits, each character 
  79. takes up 8 bytes, each byte representing a horizontal slice of the character. 
  80. It's really not that confusing after fiddling around with it. 
  81.  
  82. Program PaletteTricks; 
  83.  
  84.   Uses Crt; 
  85.  
  86.  
  87.   Const CGA_CharSet_Seg = $0F000; 
  88.         CGA_CharSet_Ofs = $0FA6E; 
  89.         CharLength      = 8; 
  90.         NumChars        = 256; 
  91.         VGA_Segment     = $0A000; 
  92.         NumCycles       = 200; 
  93.         Radius          = 80; 
  94.  
  95.         DispStr         : String = 
  96. 'Loader by THG'; 
  97.  
  98.         Colors : Array[1..15*3] Of Byte = 
  99.                  (  7,  7, 63, 
  100.                    15, 15, 63, 
  101.                    23, 23, 63, 
  102.                    31, 31, 63, 
  103.                    39, 39, 63, 
  104.                    47, 47, 63, 
  105.                    55, 55, 63, 
  106.                    63, 63, 63, 
  107.                    55, 55, 63, 
  108.                    47, 47, 63, 
  109.                    39, 39, 63, 
  110.                    31, 31, 63, 
  111.                    23, 23, 63, 
  112.                    15, 15, 63, 
  113.                     7,  7, 63  ); 
  114.  
  115.  
  116. Type  OneChar =Array[1..CharLength] Of Byte; 
  117.  
  118.  
  119. Var   CharSet : Array[1..NumChars] Of OneChar; 
  120.       Locs    : Array[1..NumCycles] Of Integer; 
  121.       BarLocs : Array[1..4] Of Integer; 
  122.  
  123.  
  124.   Procedure GetChars; 
  125.  
  126.     Var NumCounter, 
  127.         ByteCounter, 
  128.         MemCounter   :Integer; 
  129.    
  130.     Begin { GetChars } 
  131.       MemCounter:=0; 
  132.       For NumCounter:=1 To NumChars Do 
  133.         For ByteCounter:=1 To CharLength Do 
  134.           Begin 
  135.            
  136. CharSet[NumCounter][ByteCounter]:=Mem[CGA_CharSet_Seg:CGA_CharSet_Ofs          
  137. Inc(MemCounter); 
  138.           End; 
  139.     End;  { GetChars } 
  140.  
  141.  
  142.   Procedure VideoMode ( Mode : Byte ); 
  143.  
  144.     Begin { VideoMode } 
  145.       Asm 
  146.         Mov  AH,00 
  147.         Mov  AL,Mode 
  148.         Int  10h 
  149.       End; 
  150.     End;  { VideoMode } 
  151.  
  152.  
  153.   Procedure SetColor ( Color, Red, Green, Blue : Byte ); 
  154.  
  155.     Begin { SetColor } 
  156.       Port[$3C8] := Color; 
  157.       Port[$3C9] := Red; 
  158.       Port[$3C9] := Green; 
  159.       Port[$3C9] := Blue; 
  160.     End;  { SetColor } 
  161.  
  162.  
  163.   Procedure DispVert ( Var CurrLine : Integer ); 
  164.  
  165.     Var Letter : OneChar; 
  166.         VertLine, 
  167.         Count  : Integer; 
  168.  
  169.     Begin { DispVert }
  170.  
  171.       Letter := CharSet[Ord(DispStr[(CurrLine Div 8)+1])+1]; 
  172.       VertLine := (CurrLine-1) Mod 8; 
  173.       For Count := 1 To 8 Do 
  174.         If Letter[Count] And ($80 Shr VertLine) = 0 
  175.           Then Mem[VGA_Segment:185*320+(Count-1)*320+319] := 0 
  176.           Else Mem[VGa_Segment:185*320+(Count-1)*320+319] := 181; 
  177.     End;  { DispVert } 
  178.  
  179.  
  180.   Procedure CalcLocs; 
  181.  
  182.     Var Count : Integer; 
  183.  
  184.     Begin { CalcLocs } 
  185.       For Count := 1 To NumCycles Do 
  186.         Locs[Count] := Round(Radius*Sin((2*Pi/NumCycles)*Count))+Radius+1; 
  187.     End;  { CalcLocs } 
  188.  
  189.  
  190.     Procedure DoCycle; 
  191.  
  192.       Label Wait,Retr,BarLoop,PrevIsLast,Continue1,Continue2,Rep1,Rep2; 
  193.  
  194.       Begin { DoCycle } 
  195.         Asm 
  196.  
  197.           MOV   DX,3DAh 
  198. Wait:     IN    AL,DX 
  199.           TEST  AL,08h 
  200.           JZ    Wait 
  201. Retr:     IN    AL,DX 
  202.           TEST  AL,08h 
  203.           JNZ   Retr 
  204.  
  205. { Do Bars... } 
  206.  
  207.            MOV   BX,0 
  208. BarLoop: 
  209.            PUSH  BX 
  210.            MOV   AX,Word Ptr BarLocs[BX] 
  211.            MOV   BX,AX 
  212.            DEC   BX 
  213.            SHL   BX,1 
  214.            MOV   AX,Word Ptr Locs[BX] 
  215.            PUSH  AX 
  216.            CMP   BX,0 
  217.            JE    PrevIsLast 
  218.            DEC   BX 
  219.            DEC   BX 
  220.            MOV   AX,Word Ptr Locs[BX] 
  221.            JMP   Continue1 
  222.  
  223. PrevIsLast: 
  224.            MOV   AX,Word Ptr Locs[(NumCycles-1)*2] 
  225.  
  226. Continue1: 
  227.            MOV   DX,03C8h 
  228.            OUT   DX,AL 
  229.            INC   DX 
  230.            MOV   CX,15*3 
  231.            MOV   AL,0 
  232. Rep1: 
  233.            OUT   DX,AL 
  234.            LOOP  Rep1 
  235.  
  236.            DEC   DX 
  237.            POP   AX 
  238.            OUT   DX,AL 
  239.            INC   DX 
  240.            MOV   CX,15*3 
  241.            XOR   BX,BX 
  242. Rep2: 
  243.            MOV   AL,Byte Ptr Colors[BX] 
  244.            OUT   DX,AL 
  245.            INC   BX 
  246.            LOOP  Rep2 
  247.  
  248.            POP   BX 
  249.            INC   Word Ptr BarLocs[BX] 
  250.            CMP   Word Ptr BarLocs[BX],NumCycles 
  251.            JNG   Continue2 
  252.  
  253.            Mov   Word Ptr BarLocs[BX],1 
  254. Continue2: 
  255.            INC   BX 
  256.            INC   BX 
  257.            CMP   BX,8 
  258.            JNE   BarLoop 
  259.  
  260.         End; 
  261.       End;  { DoCycle } 
  262.  
  263.  
  264.   Var CurrVert, 
  265.       Count     : Integer; 
  266.       Key       : Char; 
  267.       MemPos    : Word; 
  268.  
  269.   Begin { PaletteTricks } 
  270.  
  271.     VideoMode($13); 
  272.     Port[$3C8] := 1; 
  273.     For Count := 1 To 180 Do 
  274.       SetColor(Count,0,0,0); 
  275.     MemPos := 0; 
  276.     For Count := 1 To 180 Do 
  277.       Begin 
  278.         FillChar(Mem[VGA_Segment:MemPos],320,Chr(Count)); 
  279.         MemPos := MemPos + 320; 
  280.       End; 
  281.     SetColor(181,63,63,0); 
  282.     CalcLocs; 
  283.     For Count := 1 To 4 Do 
  284.       BarLocs[Count] := Count*10; 
  285.  
  286.     GetChars; 
  287.     CurrVert := 1; 
  288.     Repeat 
  289.       DoCycle; 
  290.       For Count := 1 To 8 Do 
  291.         Move(Mem[VGA_Segment:185*320+(Count-1)*320+1], 
  292.              Mem[VGA_Segment:185*320+(Count-1)*320],319); 
  293.       DispVert(CurrVert); 
  294.       Inc(CurrVert); 
  295.       If CurrVert > Length(DispStr) * 8 
  296.         Then CurrVert := 1; 
  297.  
  298.     Until Keypressed; 
  299.     Key := ReadKey; 
  300.     VideoMode(3); 
  301.   End.  { PaletteTricks } 
  302.  
  303. ... OFFLINE 1.41 
  304.  
  305. --- Squish v1.01
  306.  * Origin: Starbase Atlantis (1:103/714)
  307.  
  308.